package asxpgyp.okhttputil.com.okhttp3demo;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.Okio;

/**
 * Created by user on 2018/1/2.
 */

public class OkHttpEngine {
    private volatile static OkHttpEngine mInstance;
    private volatile static Handler mHandler;
    private volatile static Gson gson;
    private OkHttpClient mOkHttpClient;
    private OkHttpClient.Builder builder;
    private Class classOfT;

    public static OkHttpEngine getInstance() {
        if (mInstance == null) {
            synchronized (OkHttpEngine.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpEngine();
                }
            }
        }
        return mInstance;
    }

    public OkHttpEngine() {
        mHandler = new Handler();
        gson = new Gson();
        builder = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS);
        mOkHttpClient = builder.build();
    }

    public OkHttpEngine setGsonBean(Class classOfT) {
        this.classOfT = classOfT;
        return mInstance;
    }

    public OkHttpEngine setCache(Context mContext) {
        File sdcache = mContext.getExternalCacheDir();
        int cacheSize = 10 * 1024 * 1024;
        if (sdcache != null) {
            builder.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
        }
        return mInstance;
    }

    /**
     * 异步get请求
     *
     * @param url
     * @param callback
     */
    public void getAsynHttp(String url, ResultCallback callback) {
        Request.Builder requestBuilder = new Request.Builder().url(url);
        //可以省略，默认是GET请求
        requestBuilder.method("GET", null);
        Request request = requestBuilder.build();
        Call mcall = mOkHttpClient.newCall(request);
        dealResult(mcall, callback);
    }

    /**
     * 异步post请求
     *
     * @param url
     * @param callback
     */
    public void postAsynHttp(String url, ResultCallback callback) {
        RequestBody formBody = new FormBody.Builder()
                .add("size", "10")
                .build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        Call call = mOkHttpClient.newCall(request);
        dealResult(call, callback);
    }

    /**
     * 异步上传文件
     *
     * @param url
     * @param callback
     */
    public void sendMultipart(String path, String url, ResultCallback callback) {
        MediaType MEDIA_TYPE = MediaType.parse("image/png");
        File apkFile = new File(path);
        Request.Builder builder = new Request.Builder().url(url);
        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("test", apkFile.getName(), RequestBody.create(MEDIA_TYPE, apkFile));
        MultipartBody build = bodyBuilder.build();
        RequestBody requestBody = new ProgressRequestBody(build, new ProgressRequestListener() {
            @Override
            public void onRequestProgress(long bytesWritten, long contentLength, boolean done) {
                Log.d("OkHttpEngine", "bytesWritten:" + bytesWritten + "/" + contentLength + "/" + done);
            }
        });
        builder.post(requestBody);
        Call call = mOkHttpClient.newCall(builder.build());
        dealResult(call, callback);
    }

    public void download(final Context context) {
        String url = "http://dlsw.baidu.com/sw-search-sp/soft/b2/36817/daimatongjigongjuSourceCounter.1414567613.zip";
        OkHttpClient okHttpClient = new OkHttpClient();
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.get();
        Call call = okHttpClient.newCall(builder.build());
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("TAGS", "=============onFailure===============");
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e("TAGS", "=============onResponse===============");
                Log.e("TAGS", "request headers:" + response.request().headers());
                Log.e("TAGS", "response headers:" + response.headers());
                ResponseBody responseBody = new ProgressResponseBody(response.body(), new ProgressResponseListener() {
                    @Override
                    public void onResponseProgress(long bytesRead, long contentLength, boolean done) {
                        Log.e("TAGS", "onResponseProgress:" + bytesRead + "/" + contentLength + "/" + done);
                    }
                });
                context.getFilesDir().getPath();
                BufferedSource source = responseBody.source();
                File outFile = new File(context.getFilesDir().getPath() + "/temp.apk");
                outFile.delete();
                outFile.getParentFile().mkdirs();
                outFile.createNewFile();

                BufferedSink sink = Okio.buffer(Okio.sink(outFile));
                source.readAll(sink);
                sink.flush();
                source.close();
            }
        });

    }

    /**
     * 开始网络请求
     *
     * @param call
     * @param callback
     */
    private void dealResult(Call call, final ResultCallback callback) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                sendFailedCallback(call, e, callback);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                sendSuccessCallback(call, response, callback);
            }
        });
    }

    /**
     * 成功回调
     *
     * @param call
     * @param object
     * @param callback
     * @throws IOException
     */
    private void sendSuccessCallback(final Call call, final Response object, final ResultCallback callback) throws IOException {
        final String response = object.body().string();
        Log.d("OkHttpEngine", response);
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callback != null) {
                    Object mode = gson.fromJson(response, classOfT);
                    callback.onResponse(call, mode);
                }
            }
        });
    }

    /**
     * 失败回调
     *
     * @param call
     * @param exception
     * @param callback
     */
    private void sendFailedCallback(final Call call, final IOException exception, final ResultCallback callback) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callback != null) {
                    callback.onError(call, exception);
                }
            }
        });
    }
}
